/**
 ****************************************************************************************
 *
 * @file llc_task.h
 *
 * @brief LLM task header file
 *
 * Copyright (C) RivieraWaves 2009-2015
 *
 *
 ****************************************************************************************
 */

#ifndef LLC_TASK_H_
#define LLC_TASK_H_

/**
 ****************************************************************************************
 * @addtogroup LLCTASK LLCTASK
 * @ingroup LLC
 * @brief Link Layer Controller Task
 *
 * The LLC task is responsible for managing link layer actions related to a
 * specific connection with a peer (e.g. Encryption setup, Supervision timeout, etc.). It
 * implements the state machine related to these actions.
 *
 * @{
 ****************************************************************************************
 */


/*
 * INCLUDE FILES
 ****************************************************************************************
 */
#include <stdint.h>

#include "common_bt.h"
#include "common_llcp.h"
#include "rwip_task.h" // Task definitions

#if (BLE_PERIPHERAL || BLE_CENTRAL)
/*
 * INSTANCES
 ****************************************************************************************
 */
/// Maximum number of instances of the LLC task
#define LLC_IDX_MAX  BLE_CONNECTION_MAX

/*
 * STATES
 ****************************************************************************************
 */


/// Operation type
enum llc_op_type
{
    /// Parameters update operation (initiated by local device)
    LLC_OP_LOC_PARAM_UPD        = 0x00,
    /// Parameters update operation (initiated by peer device)
    LLC_OP_REM_PARAM_UPD        = 0x01,
    /// Encryption operation
    LLC_OP_ENCRYPT              = 0x02,
    /// Data length update operation
    LLC_OP_DLE_UPD              = 0x03,
#if (BLE_2MBPS)
    /// Phys update operation (initiated by local device)
    LLC_OP_LOC_PHY_UPD          = 0x04,
#endif
    /// Max number of operations
    LLC_OP_MAX
};

/// procedure bit fields
enum llc_proc_field
{
    /// Local procedure on-going bit field
    LLC_LOC_PROC = 0,

    /// Remote procedure on-going bit field
    LLC_REM_PROC,
    /// Traffic is currently paused bit field
    LLC_TRAFFIC_PAUSED,
    /// Disconnection on-going bit field
    LLC_DISC,
};


/// Possible states of the LLC task
enum llc_state_id
{
    /// Connection ready state
    LLC_CONNECTED           = 0x00,
    /// Local procedure on-going
    LLC_LOC_PROC_BUSY       = (1 << LLC_LOC_PROC),
    /// Remote procedure on-going
    LLC_REM_PROC_BUSY       = (1 << LLC_REM_PROC),
    /// Traffic is currently paused
    LLC_TRAFFIC_PAUSED_BUSY = (1 << LLC_TRAFFIC_PAUSED),
    /// Disconnection procedure on-going
    LLC_DISC_BUSY           = ((1 << (LLC_DISC+1)) - 1),
    /// Disconnected state, connection handle ready to be used
    LLC_FREE                = 0X7F,
    /// Number of defined states.
    LLC_STATE_MAX,
};

/// Local procedure state
enum llc_loc_proc_state
{
    /// No on-going local procedure
    LLC_LOC_IDLE,
    /// wait for remote feature response
    LLC_LOC_WAIT_FEAT_RSP,
    /// Wait for peer version indication (when we initiated the procedure)
    LLC_LOC_WAIT_VERS_IND,
    /// Wait for acknowledgment of terminate indication
    LLC_LOC_WAIT_TERM_ACK,
    /// Wait for the peer response to length request
    LLC_LOC_WAIT_LENGTH_RSP,
    /// wait for LE Ping response
    LLC_LOC_WAIT_PING_RSP,

    /* **** Channel Map Update procedure **** */
    /// Wait for Channel map update instant (Master only)
    LLC_LOC_WAIT_MAP_UPD_INSTANT,

    /* **** Connection Update procedure **** */
    /// Wait for connection response packet
    LLC_LOC_WAIT_CON_PARAM_RSP,
    /// Wait for connection update PDU
    LLC_LOC_WAIT_CON_UPD_REQ,
    /// Wait for connection update instant (Master only)
    LLC_LOC_WAIT_CON_UPD_INSTANT,

    /* **** Encryption procedure **** */
    /// Wait for traffic to be paused before starting any encryption procedure
    LLC_LOC_WAIT_TRAFFIC_PAUSED,
    /// Encryption pause procedure is ongoing
    LLC_LOC_WAIT_PAUSE_ENC_RSP,
    /// Wait for pause response to be sent
    LLC_LOC_WAIT_PAUSE_ENC_RSP_SENT,

    /// Wait for encryption response
    LLC_LOC_WAIT_ENC_RSP,
    /// Wait for Session Key generated by HW AES engine or start encryption request
    LLC_LOC_WAIT_SK_AND_START_ENC_REQ,
    /// Wait for Session Key generated by HW AES engine
    LLC_LOC_WAIT_SK,
    /// Wait for start encryption request
    LLC_LOC_WAIT_START_ENC_REQ,
    /// ready to send start encryption response
    LLC_LOC_SEND_START_ENC_RSP,
    /// wait for start encryption response from slave
    LLC_LOC_WAIT_START_ENC_RSP,
    /// Wait random number generation used by SKD and IV in LL_ENC_REQ
    LLC_LOC_WAIT_RANDN_GEN_IND,

    #if(BLE_2MBPS)
    /* **** phys Update procedure **** */
    /// Wait for phys response packet
    LLC_LOC_WAIT_PHY_RSP,
    /// Wait for phys update PDU
    LLC_LOC_WAIT_PHY_UPD_REQ,
    /// Wait for phys update instant
    LLC_LOC_WAIT_PHY_UPD_INSTANT,
    /// No wait nothing change
    LLC_LOC_PHY_NO_INSTANT,
    #endif
};

/// remote procedure state
enum llc_rem_proc_state
{
    /// No on-going remote procedure
    LLC_REM_IDLE,

    /* **** Channel Map Update procedure **** */
    /// Wait for Channel map update instant (Slave only)
    LLC_REM_WAIT_MAP_UPD_INSTANT,

    /* **** Connection Update procedure **** */
    /// Wait for the host response to parameter request
    LLC_REM_WAIT_CON_PARAM_HOST_RSP,
    /// Wait for connection updae LLCP from master (Slave only)
    LLC_REM_WAIT_CON_UPD_REQ,
    /// Wait for connection update instant (Slave only)
    LLC_REM_WAIT_CON_UPD_INSTANT,

    /* **** Encryption procedure **** */
    /// Wait for traffic to be paused to handle Pause encryption request
    LLC_REM_WAIT_TP_FOR_PAUSE_ENC_REQ,
    /// Wait for pause encryption response to be received
    LLC_REM_WAIT_PAUSE_ENC_RSP,
    /// Wait for encryption  request to be received
    LLC_REM_WAIT_ENC_REQ,

    /// Wait for traffic to be paused to handle encryption request
    LLC_REM_WAIT_TP_FOR_ENC_REQ,
    /// Wait for LTK from host
    LLC_REM_WAIT_LTK,
    /// Wait for Session Key generated by HW AES engine
    LLC_REM_WAIT_SK,
    /// Wait for start encryption response
    LLC_REM_WAIT_START_ENC_RSP,
    /// Wait for TX Ack Response
    LLC_REM_WAIT_START_ENC_RSP_ACK,
    /// Wait for Encryption reject Ack Response
    LLC_REM_WAIT_ENC_REJECT_ACK,
    /// Wait random number generation used by SKD and IV in LL_ENC_REQ
    LLC_REM_WAIT_RANDN_GEN_IND,

    #if(BLE_2MBPS)
    /* **** phys Update procedure **** */
    /// Wait for phys update PDU
    LLC_REM_WAIT_PHY_UPD_REQ,
    /// Wait for phys update instant
    LLC_REM_WAIT_PHY_UPD_INSTANT,
    /// No wait nothing change
    LLC_REM_PHY_NO_INSTANT,
    #endif
};


/*
 * MESSAGES
 ****************************************************************************************
 */
/// Message API of the LLC task
enum LLC_MSG
{
    /*
     * ************** Msg HCI->LLC****************
     */
    ///Data packet from driver
    LLC_DATA_IND = TASK_FIRST_MSG(TASK_ID_LLC),

    /*
     * ************** Msg LLC->LLC****************
     */
    /* ************** Timeout ******************** */
    /// Link supervision timeout detected
    LLC_LE_LINK_SUP_TO,
    /// LLCP response timeout detected
    LLC_LLCP_RSP_TO,
    /// Authenticated payload 'nearly' time out
    LLC_AUTH_PAYL_NEARLY_TO,
    /// Authenticated payload 'real' time out.
    LLC_AUTH_PAYL_REAL_TO,
    /// Channel assessment decision timer expiration
    LLC_CHNL_ASSESS_TO,

    /* ************** procedure execution ******** */
    ///
    LLC_ENC_MGT_IND,
    /// Update link packet size procedure
    LLC_LENGTH_REQ_IND,
    /// Update channel map procedure
    LLC_CHMAP_UPDATE_REQ_IND,

    /// Start a connection update procedure
    LLC_CON_UPD_REQ_IND,
    #if (BLE_2MBPS)
    /// Start a connection update procedure
    LLC_PHY_UPD_REQ_IND,
    #endif //(BLE_2MBPS)
    /*
     * ************** LLCP messages **************
     */
    /// Handles Reception of an LLCP message
    LLC_LLCP_RECV_IND,
};

/*
 * ************** Local Defines****************
 */
/// type of tx power level
enum
{
    TX_LVL_CURRENT,
    TX_LVL_MAX,
    TX_LVL_LEN
};

/// different control state for the LLC
enum
{
    LLC_CNTL_STATE_IDLE,
    LLC_ENC_PAUSE_RESUME,
    LLC_ENC_START,
    LLC_UPDATE_CNX,
    LLC_CNTL_STATE_LEN

};
/*
 * ************** API low energy ****************
 */


/// llc le create connection request parameters structure description.
struct llc_create_con_req
{
    ///Connection handle
    uint16_t       conhdl;
    ///Scan interval
    uint16_t       scan_intv;
    ///Scan window size
    uint16_t       scan_window;
    ///Initiator filter policy
    uint8_t        init_filt_policy;
    ///Peer address type - 0=public/1=random
    uint8_t        peer_addr_type;
    ///Peer BD address
    struct bd_addr peer_addr;
    ///Own address type - 0=public/1=random
    uint8_t        own_addr_type;
    ///Minimum of connection interval
    uint16_t       con_intv_min;
    ///Maximum of connection interval
    uint16_t       con_intv_max;
    ///Connection latency
    uint16_t       con_latency;
    ///Link supervision timeout
    uint16_t       superv_to;
    ///Minimum CE length
    uint16_t       ce_len_min;
    ///Maximum CE length
    uint16_t       ce_len_max;
};

/// llc le create connection confirmation parameters structure description.
struct  llc_create_con_cfm
{
    /// status
    uint8_t         status;
    /// connection handle
    uint16_t        conhdl;
};

/// llc le create connection indication and cfm structure description.
struct  llc_create_con_req_ind
{
    /// connection interval
    uint16_t        con_int;
    /// connection latency
    uint16_t        con_lat;
    /// supervision time out
    uint16_t        sup_to;
    /// Pointer to element into the resolving list
    uint16_t        ral_ptr;
    /// peer bd address
    struct bd_addr  peer_addr;
    /// peer bd address type
    uint8_t         peer_addr_type;
    /// hopping
    uint8_t         hop_inc;
    /// sleep accuracy
    uint8_t         sleep_clk_acc;
    /// filter_policy
    uint8_t         filter_policy;
};

/// llc data rx packet structure
struct llc_data_ind
{
    /// connection handle
    uint16_t    conhdl;
    /// broadcast and packet boundary flag
    uint8_t     pb_bc_flag;
    /// length of the data
    uint16_t    length;
    /// Handle of the descriptor containing RX Data
    uint8_t     rx_hdl;
};


///llc read rssi command parameters structure
struct llc_unknown_rsp_send
{
    /// Unknown opcode
    uint8_t opcode;
};

/// Handles Reception of an LLCP message
struct llc_llcp_recv_ind
{
    /// status of LLCP unpacking
    uint8_t status;
    /// dummy byte for internal use
    uint8_t dummy;

    /// PDU data packet
    union llcp_pdu pdu;
};

/// connection update operation
enum llc_con_up_op
{
    /// Connection update requested by HCI
    LLC_CON_UP_HCI_REQ,
    /// Move the device anchor point
    LLC_CON_UP_MOVE_ANCHOR,
    /// force sending connection update request
    LLC_CON_UP_FORCE,

    /// Update connection parameter according to peer request
    LLC_CON_UP_PEER_REQ,
    /// Update connection parameter according to local request
    LLC_CON_UP_LOC_REQ,
};


/// Start a connection update procedure
struct llc_con_upd_req_ind
{
    /// requested operation
    uint8_t        operation;

    /// minimum value of connInterval
    uint16_t       con_intv_min;
    /// maximum value of connInterval
    uint16_t       con_intv_max;

    ///Connection latency
    uint16_t       con_latency;
    ///Link supervision timeout
    uint16_t       superv_to;

    ///Minimum of CE length
    uint16_t       ce_len_min;
    ///Maximum of CE length
    uint16_t       ce_len_max;


    /// minimum value of connInterval -> update request
    uint16_t       interval_min;
    /// maximum value of connInterval -> update request
    uint16_t       interval_max;

    /// preferred periodicity
    uint8_t        pref_period;
    /// ReferenceConnEventCount
    uint16_t       ref_con_event_count;
    /// Offset0
    uint16_t       offset0;
    /// Offset1
    uint16_t       offset1;
    /// Offset2
    uint16_t       offset2;
    /// Offset3
    uint16_t       offset3;
    /// Offset4
    uint16_t       offset4;
    /// Offset5
    uint16_t       offset5;
};

#if (BLE_2MBPS)
/// Phys update request indication structure definition
struct llc_phy_upd_req_ind
{
    /// requested operation
    uint8_t     operation;
    ///Phys selection
    uint8_t     all_phys;
    ///Tx phy rate
    uint8_t     tx_phys;
    ///Rx phy rate
    uint8_t     rx_phys;
    ///Status of the end of the procedure
    uint8_t     status;
};

/// Phys update operation
enum llc_phy_up_op
{
    /// Phys update requested by HCI
    LLC_PHY_UPD_HCI_REQ,
    /// Update Phys parameter according to peer request
    LLC_PHY_UPD_PEER_REQ,
    /// Update Phys parameter according to peer response
    LLC_PHY_UPD_PEER_RSP,
    /// The procedure is finished due to a reason
    LLC_PHY_UPD_TERMINATE,
};
#endif // (BLE_2MBPS)


/*
 * TASK DESCRIPTOR DECLARATIONS
 ****************************************************************************************
 */
extern const struct kernel_state_handler llc_default_handler;
extern kernel_state_t llc_state[LLC_IDX_MAX];

#endif // #if (BLE_PERIPHERAL || BLE_CENTRAL)
/// @} LLCTASK

#endif // LLC_TASK_H_
